﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DNASequencing.core.Algorithms;

namespace DNASequencing.core.data
{
    abstract class AOligonucleotide
    {
        /// <summary>
        /// Sequence of aminiacids.
        /// </summary>
        protected String _sAminoacids;

        /// <summary>
        /// Used during sequencing process, tells if this oligonucleotide was already used.
        /// </summary>
        public bool used = false;

        /// <summary>
        /// Original sequence of aminoacids. It differs from <code>getSequence()</code> when
        /// for example Backward Oligonucleotide is used.
        /// </summary>
        public String originalSequence
        {
            get
            {
                return _sAminoacids;
            }
        }

        /// <summary>
        /// Sequence of aminiacids.
        /// </summary>
        abstract public String getSequence();

        /// <summary>
        /// Creates new oligonucleotide.
        /// </summary>
        /// <param name="aminoacids">String of aminoacids.</param>
        public AOligonucleotide(String aminoacids)
        {
            _sAminoacids = aminoacids;
        }

        public List<Oligonucleotide> best = new List<Oligonucleotide>();

        //public List<AOligonucleotide> tabu = new List<AOligonucleotide>();

        //public List<AOligonucleotide> tabu2 = new List<AOligonucleotide>();

        /// <summary>
        /// Oligonucleotides that can be next to the current with
        /// some negative error or without any.
        /// </summary>
        protected List<AOligonucleotide>[] _lNext;

        /// <summary>
        /// Oligonucleotides that can be next to the current with
        /// some negative error or without any.
        /// </summary>
        public List<AOligonucleotide>[] next
        {
            get
            {
                return _lNext;
            }
        }

        /// <summary>
        /// Rating of oligonucleotide. <code>-1</code> by default.
        /// Used in algorithms for determining best followers.
        /// </summary>
        public double rating = -1;

        /// <summary>
        /// Updates the lists of next oligonucleotides depending
        /// on the set of all oligonucleotides in spectrum.
        /// </summary>
        /// <param name="all"></param>
        public void updateNext(List<AOligonucleotide> all)
        {
            bool[] used = new bool[all.Count];
            for (int i = 0; i < all.Count; ++i)
                used[i] = false;

            _lNext = new List<AOligonucleotide>[_sAminoacids.Length];
            for (int i = 0; i < _lNext.Length; ++i)
            {
                _lNext[i] = new List<AOligonucleotide>();
                for (int j = 0; j < all.Count; ++j)
                {
                    AOligonucleotide o = all.ElementAt(j);
                    //System.Console.WriteLine(this.sequence + " => [" + (i + 1) + "]: " + this.sequence.Substring(i + 1));
                    //System.Console.WriteLine(o.sequence + " => [" + (this.sequence.Length - i - 1) + "]: " + o.sequence.Substring(0, this.sequence.Length - i - 1));
                    if (_sAminoacids.Substring(i + 1) == o.getSequence().Substring(0, _sAminoacids.Length - i - 1))
                    {
                        if (!used[j])
                        {
                            _lNext[i].Add(o);
                            used[j] = true;
                        }
                    }
                }
            }
        }
    }
}
